package fun.ltool.core.excel.handler;

import fun.ltool.core.excel.annotation.ExcelEntity;
import fun.ltool.core.excel.convert.ExcelTypeConverter;
import fun.ltool.core.exceptions.ExcelException;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

/**
 * Excel数据映射处理基础类
 *
 * @param <D> 数据实体泛型
 * @author huangrongsong
 * @since 1.3
 */
public abstract class ExcelBaseHandler<D> {
    /**
     * Excel表格数据
     */
    protected final List<List<Object>> data;
    /**
     * 绑定的数据实体类型
     */
    protected final Class<D> excelMappingClass;
    /**
     * Excel数据映射 实体注解
     */
    protected final ExcelEntity excelEntity;
    /**
     * Excel数据映射 实体字段注解 的Field数据
     */
    protected final Field[] fields;

    public ExcelBaseHandler(List<List<Object>> data, Class<D> excelMappingClass, ExcelEntity excelEntity, Field[] fields) {
        this.data = data;
        this.excelMappingClass = excelMappingClass;
        this.excelEntity = excelEntity;
        this.fields = fields;
    }

    /**
     * 值转换器
     *
     * @param value         需要转换的值
     * @param fieldType     字段类型
     * @param typeConverter 转换器
     * @return 返回转换后的值
     */
    @SuppressWarnings("all")
    protected Object convertValue(Object value, Class<?> fieldType, Class<? extends ExcelTypeConverter> typeConverter) {
        if (typeConverter != ExcelTypeConverter.class) {
            ExcelTypeConverter<?> excelTypeConverter = null;
            try {
                excelTypeConverter = typeConverter.newInstance();
            } catch (InstantiationException | IllegalAccessException ex) {
                throw new ExcelException("Excel 映射实体操作，转换器处理失败", ex);
            }
            return excelTypeConverter.convert(value, fieldType);
        } else {
            return value;
        }
    }

    /**
     * 通过 行数配置读取数据行数
     *
     * @return 返回数据
     */
    protected List<List<Object>> getRowRangeLists() {
        // Excel 读取行数
        int[] rowRange = this.excelEntity.rowRange();
        List<List<Object>> list;
        // 判断是否有设置 读取行数
        if (rowRange != null && !Arrays.equals(rowRange, new int[]{0, 0})) {
            int rowStart = rowRange[0];
            if (rowRange.length > 1) {
                int rowEnd = rowRange[1];
                if (rowStart < rowEnd) {
                    if (rowEnd > this.data.size()) {
                        throw new ExcelException("设置读取的范围 注解 @ExcelEntity 属性rowRange=" + Arrays.toString(rowRange) + "大于数据的大小:" + this.data.size() + " ,请检查");
                    }
                    list = this.data.subList(rowStart, rowEnd);
                } else {
                    throw new ExcelException("注解 @ExcelEntity 属性rowRange=" + Arrays.toString(rowRange) + " 配置不正确,请检查");
                }
            } else {
                list = this.data.subList(rowStart, this.data.size());
            }
        } else {
            list = this.data;
        }
        return list;
    }

    /**
     * 通过 列数配置读取数据列数
     *
     * @param row 行数据
     * @return 返回列数据
     */
    protected List<Object> getColumnRangeLists(List<Object> row) {
        // Excel 读取列数
        int[] columnRange = excelEntity.columnRange();
        List<Object> list;
        // 判断是否有设置 读取行数
        if (columnRange != null && !Arrays.equals(columnRange, new int[]{0, 0})) {
            int columnStart = columnRange[0];
            if (columnRange.length > 1) {
                int columnEnd = columnRange[1];
                if (columnStart < columnEnd) {
                    if (columnEnd > row.size()) {
                        list = row;
                    } else {
                        list = row.subList(columnStart, columnEnd);
                    }
                } else {
                    throw new ExcelException("注解 @ExcelEntity 属性rowRange=" + Arrays.toString(columnRange) + " 配置不正确,请检查");
                }
            } else {
                list = row.subList(columnStart, row.size());
            }
        } else {
            list = row;
        }
        return list;
    }

    /**
     * 通过行列数组获取单元格
     *
     * @param cell 单元格数组 由行列组成
     * @param list 表格数据
     * @return 返回cell值
     */
    protected Object getCell(int[] cell, List<List<Object>> list) {
        if (cell == null || cell.length == 0) {
            return null;
        }
        if (list == null || list.isEmpty()) {
            return null;
        }
        if (list.size() <= cell[0]) {
            return null;
        }
        List<Object> row = list.get(cell[0]);
        if (row == null || row.isEmpty() || row.size() <= cell[1]) {
            return null;
        }
        return row.get(cell[1]);
    }
}
